/*
 * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.test

import org.junit.jupiter.api.extension.ConditionEvaluationResult
import org.junit.jupiter.api.extension.ExecutionCondition
import org.junit.jupiter.api.extension.ExtensionContext
import java.io.File
import kotlin.jvm.optionals.getOrNull

/*
 * Disables tests based on "excludes file" generated by TeamCity's Parallel Tests feature.
 * Workaround for #KTI-2074
 */
class TCParallelTestsExecutionCondition : ExecutionCondition {
    lateinit var excludedTestClasses: Set<String>
    override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult {
        if (!::excludedTestClasses.isInitialized) {
            excludedTestClasses = context.getConfigurationParameter("teamcity.build.parallelTests.excludesFile") { excludesFile ->
                File(excludesFile).readLines().filter { !it.startsWith("#") }.toSet()
            }.getOrNull() ?: emptySet()
        }

        if (excludedTestClasses.isEmpty()) {
            return ConditionEvaluationResult.enabled("TeamCity Parallel Tests excludes file is not present")
        }

        // Disabling a test class also disables all inner test classes.
        // To be able to disable a test separately from inner tests, we need to work on a test method level.
        if (!context.testMethod.isPresent) {
            return ConditionEvaluationResult.enabled("The execution condition is only applicable to test methods")
        }

        return if (context.testClass.getOrNull()?.name in excludedTestClasses) {
            ConditionEvaluationResult.disabled("Disabled in the current batch by TeamCity Parallel Tests feature")
        } else {
            ConditionEvaluationResult.enabled("Not disabled in the current batch by TeamCity Parallel Tests feature")
        }
    }
}